package org.oimwrapper.connectors.internal;

import Thor.API.*;
import Thor.API.Operations.*;
import com.thortech.util.logging.*;
import com.thortech.xl.dataaccess.*;
import com.thortech.xl.dataobj.util.*;
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;

/**
 * This provides functions for managing email definitions and notifications.
 * 
 * THIS IS AN INTERNAL CLASS AND SHOULD NOT BE USED DIRECTLY.
 */
public final class OIMEmailUtilities {

	/**
	 * The default logger instance for this instance.
	 */
	private Logger logger;

	/**
	 * The email operations instance that backs this object.
	 */
	private tcEmailOperationsIntf emailOp;

	/**
	 * The property operations instance that backs this object.
	 */
	private tcPropertyOperationsIntf propertyOp;
	
	/**
	 * The data provider used by this object.
	 */
	private tcDataProvider database;
	
	/**
	 * The default MIME type to use when not specified.
	 */
	private String defaultMimeType;

	/**
	 * The default constructor.
	 * 
	 * @param ClassLogger The Logger used by the invoking class.
	 * @param EmailOp The email operations utility used by the invoking class.
	 * @param PropertyOp The property operations utility used by the invoking class.
	 * @param Database The data provider from the invoking class.
	 */
	protected OIMEmailUtilities(Logger ClassLogger, tcEmailOperationsIntf EmailOp, tcPropertyOperationsIntf PropertyOp, tcDataProvider Database) {
		logger = ClassLogger;
		emailOp = EmailOp;
		propertyOp = PropertyOp;
		database = Database;
		defaultMimeType = "text/plain";
	}

	/**
	 * Retrieves the key for a given email defintion.
	 *
	 * @param Name The name of the email definition to retrieve the key for.
	 * @return The key of the email definition, or 0 if the email definition is not
	 *         found.
	 * @exception Exception
	 */
	public long getEmailDefinition(String Name) throws Exception {
		logger.debug("Entering emailUtilities.getEmailDefinition()");
		long result = 0L;
		Map searchFor = new HashMap();
		searchFor.put("Email Definition.Name", Name);
		tcResultSet results = emailOp.findEmailDefinition(searchFor);
		if (results.getRowCount() == 1) {
			results.goToRow(0);
			result = results.getLongValue("Email Definition.Key");
		}
		logger.debug("Exiting emailUtilities.getEmailDefinition()");
		return result;
	}
	
	/**
	 * Retrieves the name for a given email defintion.
	 *
	 * @param Key The key of the email definition to retrieve the name for.
	 * @return The name of the email definition, or an empty string if the email 
	 *         definition is not found.
	 * @exception Exception
	 */
	public String getEmailDefinition(long Key) throws Exception {
		logger.debug("Entering emailUtilities.getEmailDefinition()");
		String result = "";
		Map searchFor = new HashMap();
		searchFor.put("Email Definition.Key", Long.toString(Key));
		tcResultSet results = emailOp.findEmailDefinition(searchFor);
		if (results.getRowCount() == 1) {
			results.goToRow(0);
			result = results.getStringValue("Email Definition.Name");
		}
		logger.debug("Exiting emailUtilities.getEmailDefinition()");
		return result;
	}

	/**
	 * Retrieves the name of the IT resource used for sending email from OIM.
	 *
	 * @return The name of the IT resource used to send email notices.
	 * @exception Exception
	 */
	public String getEmailITResource() throws Exception {
		logger.debug("Entering emailUtilities.getEmailITResource()");
		String result = propertyOp.getPropertyValue("XL.MailServer");
		logger.debug("Exiting emailUtilities.getEmailITResource()");
		return result;
	}
	
	/**
	 * Sends an email message.
	 *
	 * @param Subject The subject of the email message to send.
	 * @param Body The body of the email message to send.
	 * @param From The from address to use on the email message.
	 * @param Recipient The recipients for the message.   All recipients will be placed in the 'TO' field.
	 * @param ITResourceData A Map containing the attribute value pairs for the IT resource used to send mail through.
	 * @param MimeType The MIME Type to use for the body.
	 * @exception Exception
	 */
	public void sendEmail(String Subject, String Body, String From, String Recipient, Map ITResourceData, String MimeType) throws Exception {
		logger.debug("Entering emailUtilities.sendEmail()");
		Map recipients = new HashMap();
		if (Recipient != null) {
			String[] addresses = Recipient.replaceAll(",", ";").split(";");
			for (int i = 0; i < addresses.length; i++) {
				recipients.put(addresses[i], "TO");
			}
		}
		sendEmail(Subject, Body, From, recipients, ITResourceData, MimeType);
		logger.debug("Exiting emailUtilities.sendEmail()");
	}

	/**
	 * Sends an email message.
	 *
	 * @param Subject The subject of the email message to send.
	 * @param Body The body of the email message to send.
	 * @param From The from address to use on the email message.
	 * @param Recipients A Map of the recipient types and the type for each.  Valid types include <code>TO</code>,
	 *                   <code>CC</code>, or <code>BCC</code>.
	 * @param ITResourceData A Map containing the attribute value pairs for the IT resource used to send mail through.
	 * @param MimeType The MIME Type to use for the body.
	 * @exception Exception
	 */
	public void sendEmail(String Subject, String Body, String From, Map Recipients, Map ITResourceData, String MimeType) throws Exception {
		logger.debug("Entering emailUtilities.sendEmail()");
		logger.debug("From: " + From == null ? "<null>" : From);
		logger.debug("To: " + Recipients == null ? "<null>" : Recipients.toString());
		logger.debug("Subject: " + Subject == null ? "<null>" : Subject);
		String mimeType = MimeType == null || MimeType.length() == 0 ? defaultMimeType : MimeType;
		logger.debug("MimeType: " + mimeType);
		logger.debug(Body == null ? "<null>" : Body);
		Session session = null;
		Properties env = new Properties();
		env.put("mail.smtp.host", ITResourceData.get("Server Name"));
		if (ITResourceData.get("Authentication") != null && ((String) ITResourceData.get("Authentication")).equalsIgnoreCase("true")) {
			env.put("mail.smtp.auth", "true");
			String username = (String) ITResourceData.get("User Login");
			String password = (String) ITResourceData.get("User Password");
			session = Session.getDefaultInstance(env, new SMTPAuth(username, password));
		} else {
			session = Session.getDefaultInstance(env);
		}
		Message message = new MimeMessage(session);
		message.setFrom(new InternetAddress(From));
		if (Recipients != null) {
			for (Iterator iterator = Recipients.keySet().iterator(); iterator.hasNext(); ) {
				String address = (String) iterator.next();
				String type = (String) Recipients.get(address);
				if (type.equalsIgnoreCase("TO")) {
					message.addRecipient(Message.RecipientType.TO, new InternetAddress(address));
				} else if (type.equalsIgnoreCase("CC")) {
					message.addRecipient(Message.RecipientType.CC, new InternetAddress(address));
				} else if (type.equalsIgnoreCase("BCC")) {
					message.addRecipient(Message.RecipientType.BCC, new InternetAddress(address));
				}
			}
		}
		message.setSubject(Subject);
		message.setContent(Body, mimeType);
		message.saveChanges();
		Transport.send(message);
		logger.debug("Exiting emailUtilities.sendEmail()");
	}
	
	/**
	 * This is a basic authenticator for SMTP.
	 */
	protected class SMTPAuth extends Authenticator {

		/**
		 * The username used for authentication to the SMTP server.
		 */
		private String username;

		/**
		 * The password used for authentication to the SMTP server.
		 */
		private String password;

		/**
		 * The default constructor.
		 *
		 * @param Username The username to authenticate to the SMTP server with.
		 * @param Password The password to authenticate to the SMTP server with.
		 */
		public SMTPAuth(String Username, String Password) {
			username = Username;
			password = Password;
		}

		/**
		 * Returns the PasswordAuthentication structure for this instance.
		 *
		 * @return The PasswordAuthentication structure for this isntance.
		 */
		public PasswordAuthentication getPasswordAuthentication() {
			return new PasswordAuthentication(username, password);
		}
	}

	/**
	 * Sends an email based on email definition for a approval request.
	 *
	 * @param EmailDefinitionKey The key of the email definition to use.
	 * @param Recipient The recipient email address of this message.
	 * @param ITResourceData A Map containing the attribute value pairs for the IT resource used to send mail through.
	 * @param RequestKey The key of the request that sends this email.
	 * @exception Exception
	 */
	public void sendApprovalEmail(long EmailDefinitionKey, String Recipient, Map ITResourceData, long RequestKey) throws Exception {
		logger.debug("Entering emailUtilities.sendApprovalEmail()");
		String subject = emailOp.getEmailSubject(EmailDefinitionKey);
		String body = emailOp.getRequestEmailBody(EmailDefinitionKey, RequestKey);
		String from = emailOp.getRequestEmailFrom(EmailDefinitionKey, RequestKey);
		sendEmail(subject, body, from, Recipient, ITResourceData, defaultMimeType);
		logger.debug("Exiting emailUtilities.sendApprovalEmail()");
	}
	
	/**
	 * Sends an email based on email definition for a approval request.
	 *
	 * @param EmailDefinitionKey The key of the email definition to use.
	 * @param Recipients A Map of the recipient types and the type for each.  Valid types include <code>TO</code>,
	 *                   <code>CC</code>, or <code>BCC</code>.
	 * @param ITResourceData A Map containing the attribute value pairs for the IT resource used to send mail through.
	 * @param RequestKey The key of the request that sends this email.
	 * @exception Exception
	 */
	public void sendApprovalEmail(long EmailDefinitionKey, Map Recipients, Map ITResourceData, long RequestKey) throws Exception {
		logger.debug("Entering emailUtilities.sendApprovalEmail()");
		String subject = emailOp.getEmailSubject(EmailDefinitionKey);
		String body = emailOp.getRequestEmailBody(EmailDefinitionKey, RequestKey);
		String from = emailOp.getRequestEmailFrom(EmailDefinitionKey, RequestKey);
		sendEmail(subject, body, from, Recipients, ITResourceData, defaultMimeType);
		logger.debug("Exiting emailUtilities.sendApprovalEmail()");
	}

	/**
	 * Sends an email based on email definition for a provisioning task.
	 *
	 * @param EmailDefinitionKey The key of the email definition to use.
	 * @param Recipient The recipient email address of this message.
	 * @param ITResourceData A Map containing the attribute value pairs for the IT resource used to send mail through.
	 * @param TaskInstanceKey The key of the process task instance that sends this email.
	 * @exception Exception
	 */
	public void sendProvisioningEmail(long EmailDefinitionKey, String Recipient, Map ITResourceData, long TaskInstanceKey) throws Exception {
		logger.debug("Entering emailUtilities.sendProvisioningEmail()");
		String subject = emailOp.getEmailSubject(EmailDefinitionKey);
		String body = emailOp.getProvisioningEmailBody(EmailDefinitionKey, TaskInstanceKey);
		String from = emailOp.getProvisioningEmailFrom(EmailDefinitionKey, TaskInstanceKey);
		sendEmail(subject, body, from, Recipient, ITResourceData, defaultMimeType);
		logger.debug("Exiting emailUtilities.sendProvisioningEmail()");
	}
	
	/**
	 * Sends an email based on email definition for a provisioning task.
	 *
	 * @param EmailDefinitionKey The key of the email definition to use.
	 * @param Recipients A Map of the recipient types and the type for each.  Valid types include <code>TO</code>,
	 *                   <code>CC</code>, or <code>BCC</code>.
	 * @param ITResourceData A Map containing the attribute value pairs for the IT resource used to send mail through.
	 * @param TaskInstanceKey The key of the process task instance that sends this email.
	 * @exception Exception
	 */
	public void sendProvisioningEmail(long EmailDefinitionKey, Map Recipients, Map ITResourceData, long TaskInstanceKey) throws Exception {
		logger.debug("Entering emailUtilities.sendProvisioningEmail()");
		String subject = emailOp.getEmailSubject(EmailDefinitionKey);
		String body = emailOp.getProvisioningEmailBody(EmailDefinitionKey, TaskInstanceKey);
		String from = emailOp.getProvisioningEmailFrom(EmailDefinitionKey, TaskInstanceKey);
		sendEmail(subject, body, from, Recipients, ITResourceData, defaultMimeType);
		logger.debug("Exiting emailUtilities.sendProvisioningEmail()");
	}
	
	/**
	 * Sends an email based on that user's data.
	 *
	 * @param EmailDefinition The name of the email definition to use.
	 * @param Recipient The recipient email address of this message.
	 * @param ITResourceData A Map containing the attribute value pairs for the IT resource used to send mail through.
	 * @param UserKey The key of the user that the email is generated about.
	 * @exception Exception
	 */
	public void sendGeneralEmail(String EmailDefinition, String Recipient, Map ITResourceData, long UserKey) throws Exception {
		logger.debug("Entering emailUtilities.sendGeneralEmail()");
		tcEmailNotificationUtil emailUtil = new tcEmailNotificationUtil(database);
		emailUtil.constructPasswordEmail(EmailDefinition, Long.toString(UserKey));
		sendEmail(emailUtil.getSubject(), emailUtil.getBody(), emailUtil.getFromAddress(), Recipient, ITResourceData, defaultMimeType);
		logger.debug("Exiting emailUtilities.sendGeneralEmail()");
	}
	
	/**
	 * Sends an email based on that user's data.
	 *
	 * @param EmailDefinition The name of the email definition to use.
	 * @param Recipients A Map of the recipient types and the type for each.  Valid types include <code>TO</code>,
	 *                   <code>CC</code>, or <code>BCC</code>.
	 * @param ITResourceData A Map containing the attribute value pairs for the IT resource used to send mail through.
	 * @param UserKey The key of the user that the email is generated about.
	 * @exception Exception
	 */
	public void sendGeneralEmail(String EmailDefinition, Map Recipients, Map ITResourceData, long UserKey) throws Exception {
		logger.debug("Entering emailUtilities.sendGeneralEmail()");
		tcEmailNotificationUtil emailUtil = new tcEmailNotificationUtil(database);
		emailUtil.constructPasswordEmail(EmailDefinition, Long.toString(UserKey));
		sendEmail(emailUtil.getSubject(), emailUtil.getBody(), emailUtil.getFromAddress(), Recipients, ITResourceData, defaultMimeType);
		logger.debug("Exiting emailUtilities.sendGeneralEmail()");
	}
}